﻿using AdminApi.Extension.Permission.Model;
using AdminApi.Extension.Utils;
using Application.Admin;
using Domain.Services;
using DTO.Admin;
using Infrastructure;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using static Microsoft.AspNetCore.Mvc.ApiResultExtensions;

namespace AdminApi.Extension.Permission
{
    public class AuthFilter : IAuthorizationFilter, IOrderedFilter
    {
        public AdminApplication adminApplication { get; set; }
        public int Order => 0;
        public AuthFilter(AdminApplication adminApplication)
        {
            this.adminApplication = adminApplication;
        }

        public void OnAuthorization(AuthorizationFilterContext context)
        {
            ControllerActionDescriptor controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;

            if (controllerActionDescriptor.MethodInfo.GetCustomAttribute<AllowAnonymousAttribute>() != null
                || controllerActionDescriptor.ControllerTypeInfo.GetCustomAttribute<AllowAnonymousAttribute>() != null)
            {
                return;
            }

            Dictionary<string, object> payLoad = null;
            var authorization = context.HttpContext.Request.Headers["Authorization"].FirstOrDefault();
            if (String.IsNullOrWhiteSpace(authorization)) authorization = context.HttpContext.Request.Headers["authorization"].FirstOrDefault();

            var pauthorization = authorization;
            if (!string.IsNullOrWhiteSpace(pauthorization))
            {
                if (pauthorization.StartsWith("Bearer "))
                {
                    pauthorization = pauthorization.Substring("Bearer ".Length).Trim();
                }
                else if (pauthorization.StartsWith("bearer "))
                {
                    pauthorization = pauthorization.Substring("bearer ".Length).Trim();
                }

                if (JwtUtils.Validate(pauthorization))
                {
                    var parr = pauthorization.Split('.');

                    string pencodedPayload = Microsoft.IdentityModel.Tokens.Base64UrlEncoder.Decode(parr[1]);

                    payLoad = JsonConvert.DeserializeObject<Dictionary<string, object>>(pencodedPayload);

                    context.HttpContext.Items["payLoad"] = payLoad;
                }
            }

            var mtoken = controllerActionDescriptor.MethodInfo.MetadataToken;

            PermissionMenuInfo perssionMenuInfo = PressionManager.GetPerssionMenuInfoByMetadataToken(mtoken);

            if (perssionMenuInfo == null) return;

            if (payLoad == null)
            {
                context.Result = new UnauthorizedResult();
                return;
            }

            var pid = int.Parse(payLoad["adminId"].ToString());


            if (adminApplication.IsLoginTimeOut(payLoad))
            {
                var time = DateTime.Parse(payLoad["time"].ToString());
                var expires = int.Parse(payLoad["expires"].ToString());

                if (time.AddMinutes(expires).AddHours(12) <= DateTime.Now)
                {
                    context.Result = new UnauthorizedResult();
                    return;
                }

                AdminLoginOutput adminLoginOutput = new AdminLoginOutput();
                var encodeJwt = JwtUtils.CreateToken(payLoad, 120);
                adminLoginOutput.Token = encodeJwt;
                adminLoginOutput.Expire = 7200;

                ApiReturn tlhReturn = new ApiReturn(adminLoginOutput, ResultCode.Sucess, "刷新Token", false);

                ContentResult contentResult = new ContentResult();
                contentResult.StatusCode = 412;
                contentResult.ContentType = "application/json";
                contentResult.Content = JsonConvert.SerializeObject(tlhReturn);

                context.Result = contentResult;

                return;
            }

            ISet<String> AdminPressionSet = null;

            if (pid == 1)
            {
                AdminPressionSet = new HashSet<string>();
                AdminPressionSet.Add("*");
            }
            else
            {
                AdminPressionSet = adminApplication.GetPressions(pid, false);
            }

            if (pid != 1 && !AdminPressionSet.Contains(perssionMenuInfo.ID))
            {
                StatusCodeResult statusCodeResult = new StatusCodeResult(403);
                context.Result = statusCodeResult;
                return;
            }


            context.HttpContext.Items["AdminId"] = pid;
            context.HttpContext.Items["AdminPressionSet"] = AdminPressionSet;
        }

        /// <summary>
        ///  请求验证，当前验证部分不要抛出异常，ExceptionFilter不会处理
        /// </summary>
        /// <param name="context">请求内容信息</param>
        //public override async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        //{
        //    ControllerActionDescriptor controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;

        //    if (controllerActionDescriptor.MethodInfo.GetCustomAttribute<AllowAnonymousAttribute>(inherit: true) != null
        //        || controllerActionDescriptor.ControllerTypeInfo.GetCustomAttribute<AllowAnonymousAttribute>() != null)
        //    {
        //        return;
        //    }

        //    var mtoken = controllerActionDescriptor.MethodInfo.MetadataToken;

        //    PerssionMenuInfo perssionMenuInfo = PressionManager.GetPerssionMenuInfoByMetadataToken(mtoken);

        //    if (perssionMenuInfo == null) return;

        //    var authorization = context.HttpContext.Request.Headers["Authorization"].FirstOrDefault();
        //    if (String.IsNullOrWhiteSpace(authorization)) authorization = context.HttpContext.Request.Headers["authorization"].FirstOrDefault();

        //    if (string.IsNullOrWhiteSpace(authorization))
        //    {
        //        //context.Result = new TlhReturn(null, ResultCode.NoLogin, "账号未登录", false);
        //        StatusCodeResult statusCodeResult = new StatusCodeResult(401);
        //        context.Result = statusCodeResult;
        //        return;
        //    }

        //    if (authorization.StartsWith("Bearer "))
        //    {
        //        authorization = authorization.Substring("Bearer ".Length).Trim();
        //    }
        //    else if (authorization.StartsWith("bearer "))
        //    {
        //        authorization = authorization.Substring("bearer ".Length).Trim();
        //    }

        //    if (!JwtUtils.Validate(authorization))
        //    {
        //        //context.Result = new TlhReturn(null, ResultCode.NoLogin, "登录状态失效", false);
        //        StatusCodeResult statusCodeResult = new StatusCodeResult(401);
        //        context.Result = statusCodeResult;
        //        return;
        //    }

        //    Dictionary<string, object> payLoad = JsonConvert.DeserializeObject<Dictionary<string, object>>(authorization);            

        //    var pid = int.Parse(payLoad["pid"].ToString());

        //    AdminBusiness adminBusiness = ServiceProvider.GetService<AdminBusiness>();
        //    ISet<String> AdminPressionSet = null;

        //    if (pid == 1)
        //    {
        //        AdminPressionSet = new HashSet<string>();
        //        AdminPressionSet.Add("*");
        //    }
        //    else
        //    {
        //        AdminPressionSet = adminBusiness.GetPressions(pid);
        //    }

        //    if (!AdminPressionSet.Contains(perssionMenuInfo.ID))
        //    {
        //        StatusCodeResult statusCodeResult = new StatusCodeResult(403);
        //        context.Result = statusCodeResult;
        //        return;
        //    }

        //}


        //判断是否不需要权限

        //public static bool IsHaveAllow(AuthorizationFilterContext context)
        //{

        //    if (context.ActionDescriptor.)
        //    {

        //    }


        //    return false;

        //}
    }
}
